package org.stars.daostars.sqlmapper.loader.xml;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.stars.daostars.core.Profile;
import org.stars.daostars.core.SqlFragment;
import org.stars.daostars.core.SqlQuery;
import org.stars.daostars.core.parser.PipelineChecker;
import org.stars.daostars.core.parser.Preprocessor;
import org.stars.daostars.core.parser.SqlParser;
import org.stars.daostars.core.parser.VariablesChecker;
import org.stars.daostars.sqlmapper.SqlMapper;
import org.stars.util.StringUtility;

import org.xml.sax.Attributes;

/**
 * Handler del tag dao
 * 
 * @author Francesco Benincasa (908099)
 *
 */
public abstract class DaoTagHandler {
	
	protected static Log getLog()
	{
		return LogFactory.getLog(DaoTagHandler.class);
	}
	
 
	private static final String NAME = "name";
	private static final String CONNECTION = "connection";

	/**
	 * Analizza il tag DAO. Gli attributi gestiti sono:
	 * <ul>
	 * <li>name: nome del dao. Se non specificato viene usato il nome del file</li>
	 * <li>connection: nome della connessione. Se non specificato, viene usata la connessione di default.</li>
	 * </ul>
	 * @param currentFileName
	 * @param attributes
	 * @return
	 */
	public static SqlMapper startElement(Profile profile, String fileName, Attributes attributes) {
		//Logger log=getLogger();
		// come daoName mette l'attributo name o il nome del file
		String currentDaoName = StringUtility.nvl(attributes.getValue(NAME), fileName).toUpperCase().trim();
		
		// prendiamo la connessione dalla definizione
		String connection = StringUtility.nvl(attributes.getValue(CONNECTION));
				
		if (connection.length() == 0)
		{
			// non è definita la connessione, prendiamo quella del profilo
			connection = profile.getDefaultConnectionName();
		}

		// creiamo una nuova definizione di dao.
		SqlMapper daoDefinition = new SqlMapper(currentDaoName, connection);

		return daoDefinition;
	}
	
	/**
	 * Termina l'analisi della definizione del dao.
	 * 
	 * @param definition
	 */
	public static void endElement(SqlMapper definition)
	{
		Log log=getLog();
		try {

			Preprocessor.execute(definition);

			// preprocessiamo tutte le query per
			// individuare le query condizionali
			for (SqlQuery query : definition.getQuerySet().values()) {
				try {
					List<SqlFragment> clauses = SqlParser.parse(query.getPlainSql());
					query.setClauses(clauses);
				} catch (Exception e) {
					String msg=e.getClass().getSimpleName()+" = " + e.getMessage();
					log.error("------------------------------------------");
					log.error(msg);
					definition.addParserError(msg, e.getClass());
					log.error("------------------------------------------");
				}
			}

			// analizziamo tutte le query per le variabili
			try {
				boolean bRet = VariablesChecker.checkForVariableBinding(definition);
				if (bRet) {
					log.debug("Parsing dao " + definition.getName() + " for variables OK");
				} else {
					String msg="Parsing dao " + definition.getName() + " for variables ends with ERROR(S)";					
					definition.addParserError(msg);
					log.error("------------------------------------------");
					log.error(msg);
					log.error("------------------------------------------");
				}
			} catch (Exception e) {
			}

			// analizziamo tutte le pipeline
			try {
				boolean bRet = PipelineChecker.checkForVariableBinding(definition);
				if (bRet) {
					log.debug("Parsing dao " + definition.getName() + " for pipeline OK");
				} else {
					String msg="Parsing dao " + definition.getName() + " for pipeline ends with ERROR(S)";
					definition.addParserError(msg);
					log.error("------------------------------------------");
					log.error(msg);
					log.error("------------------------------------------");
				}

			} catch (Exception e) {

			}
		} catch (Exception e) {
			definition.addParserError(e.getMessage(), e.getClass());
			String msg=e.getClass().getSimpleName()+" = " + e.getMessage();
			log.error("------------------------------------------");
			log.error(msg);
			log.error("------------------------------------------");
		}		
	}
}
